﻿// <copyright file="ValidationReportForm.cs" company="City of Portland, BES-ASM">
// </copyright>
// <summary>ValidationReportForm dialog</summary>

namespace BESASM.EMGAATS.UI
{
  using System;
  using System.Collections.Generic;
  using System.ComponentModel;
  using System.Data;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  using System.Windows.Forms;
  using BESASM.EMGAATS.BusinessClasses;
  using FluentValidation.Results;

  /// <summary>
  /// A form for reporting validation errors
  /// </summary>
  public partial class ValidationReportForm : Form
  {
    private bool updatingLevels = false;

    /// <summary>
    /// Initializes a new instance of the <see cref="ValidationReportForm"/> class.
    /// </summary>
    /// <param name="result">The validation result to display.</param>
    public ValidationReportForm(ValidationResult result)
    {
      this.InitializeComponent();

      this.ValidationResult = result;
    }

    /// <summary>
    /// Raised when the selection of validation failures has changed
    /// </summary>
    public event EventHandler<EventArgs> SelectionChanged;

    /// <summary>
    /// Gets the validation results displayed in this dialog.
    /// </summary>
    public ValidationResult ValidationResult { get; private set; }

    /// <summary>
    /// Gets a list of the user selected failures.
    /// </summary>
    public IList<ValidationFailure> SelectedFailures
    {
      get
      {
        return this.failuresListBox.SelectedItems.Cast<ValidationFailure>().ToList();
      }
    }

    /// <summary>
    /// Gets a value indicating whether the client should zoom to the selected
    /// </summary>
    public bool ZoomToSelected
    {
      get
      {
        // TODO: Create event args to pass this info out
        return this.zoomCheckBox.Visible && this.zoomCheckBox.Checked;
      }
    }

    /// <summary>
    /// Called when the form is loaded.
    /// </summary>
    /// <param name="e">The event parameters for this event.</param>
    protected override void OnLoad(EventArgs e)
    {
      base.OnLoad(e);

      this.UpdateErrorLevels();
      this.UpdateValidationList();
      this.UpdatePropertiesButton();
      this.UpdateEventControls();
    }

    /// <summary>
    /// Called when the selection of validation failures has changed.
    /// </summary>
    protected void OnSelectionChanged()
    {
      if (this.SelectionChanged != null)
      {
        this.SelectionChanged(this, new EventArgs());
      }
    }

    private void UpdateErrorLevels()
    {
      this.updatingLevels = true;

      bool hasErrors = false;
      bool hasWarnings = false;
      bool hasInfo = false;

      if (this.ValidationResult != null)
      {
        hasErrors = this.ValidationResult.HasErrors();
        hasWarnings = this.ValidationResult.HasWarnings();
        hasInfo = this.ValidationResult.HasInfo();
      }

      this.errorCheckBox.Enabled = hasErrors;
      this.errorCheckBox.Checked = hasErrors;
      this.errorCheckBox.BackColor = hasErrors ? Color.LightCoral : SystemColors.Control;

      this.warningsCheckBox.Enabled = hasWarnings;
      this.warningsCheckBox.Checked = hasWarnings;
      this.warningsCheckBox.BackColor = hasWarnings ? Color.Khaki : SystemColors.Control;

      this.infoCheckBox.Enabled = hasInfo;
      this.infoCheckBox.Checked = hasInfo;
      this.infoCheckBox.BackColor = hasInfo ? Color.LightSteelBlue : SystemColors.Control;

      this.updatingLevels = false;
    }

    private void UpdateValidationList()
    {
      if (this.updatingLevels)
      {
        return;
      }

      this.failuresListBox.Items.Clear();

      if (this.ValidationResult != null)
      {
        if (this.errorCheckBox.Checked)
        {
          this.failuresListBox.Items.AddRange(this.ValidationResult.Errors.Where(f => f.IsError()).ToArray());
        }

        if (this.warningsCheckBox.Checked)
        {
          this.failuresListBox.Items.AddRange(this.ValidationResult.Errors.Where(f => f.IsWarning()).ToArray());
        }

        if (this.infoCheckBox.Checked)
        {
          this.failuresListBox.Items.AddRange(this.ValidationResult.Errors.Where(f => f.IsInfo()).ToArray());
        }
      }
    }

    private void UpdateEventControls()
    {
      this.synchCheckBox.Visible = this.SelectionChanged != null;
      this.zoomCheckBox.Visible = this.SelectionChanged != null;
    }

    private void PropertiesButton_Click(object sender, EventArgs e)
    {
      foreach (ValidationFailure failure in this.SelectedFailures)
      {
        if (failure.SourceObject() is IEntity)
        {
          IEntity entity = (IEntity)failure.SourceObject();
          switch (entity.EntityType)
          {
            case EntityType.Link:
              LinkPropertyEditor linkEditor = new LinkPropertyEditor() { Link = (ILink)entity };
              linkEditor.ShowDialog(this);
              break;
            case EntityType.Node:
              NodePropertyEditor nodeEditor = new NodePropertyEditor() { Node = (INode)entity };
              nodeEditor.ShowDialog(this);
              break;
            case EntityType.Area:
              AreaPropertyEditor areaEditor = new AreaPropertyEditor() { Area = (IArea)entity };
              areaEditor.ShowDialog(this);
              break;
            case EntityType.Director:
              DirectorPropertyEditor directorEditor = new DirectorPropertyEditor() { Director = (IDirector)entity };
              directorEditor.ShowDialog(this);
              break;
          }

          break;
        }
      }
    }

    private void FailuresListBox_SelectedIndexChanged(object sender, EventArgs e)
    {
      this.UpdatePropertiesButton();

      if (this.synchCheckBox.Checked)
      {
        this.OnSelectionChanged();
      }
    }

    private void UpdatePropertiesButton()
    {
      bool entityFound = false;
      if (this.SelectedFailures.Count > 0)
      {
        foreach (ValidationFailure failure in this.SelectedFailures)
        {
          if (failure.SourceObject() is IEntity)
          {
            entityFound = true;
            break;
          }
        }
      }

      this.propertiesButton.Enabled = entityFound;
    }

    private void SynchCheckBox_CheckedChanged(object sender, EventArgs e)
    {
      if (this.synchCheckBox.Checked)
      {
        this.zoomCheckBox.Enabled = true;
        this.OnSelectionChanged();
      }
      else
      {
        // TODO: Always keep zoom to selection enabled and zoom, but do not select
        this.zoomCheckBox.Enabled = false;
      }
    }

    private void ErrorLevelCheckBox_CheckedChanged(object sender, EventArgs e)
    {
      this.UpdateValidationList();
    }

    private void FailuresListBox_DoubleClick(object sender, EventArgs e)
    {
      if (this.propertiesButton.Enabled)
      {
        this.PropertiesButton_Click(this.failuresListBox, new EventArgs());
      }
    }

    private void CloseButton_Click(object sender, EventArgs e)
    {
      this.Close();
    }
  }
}
